home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / DOS / PG / CHART.ZIP / CSUB3.86 < prev    next >
Encoding:
Text File  |  1994-01-02  |  29.3 KB  |  1,190 lines

  1.  
  2.         ;get following box
  3.  
  4. get_follow_box:
  5.         mov ax,w box    ;load follow box
  6.         mov cx,ax    ;save it
  7.         mov bx,w follow_route    ;load following route
  8.         call get_box_par    ;get box route of following box
  9.         mov bx,ax
  10.         mov ax,cx    ;load following box
  11.         call get_route    ;get its box route of
  12.         ret    ;exit
  13.  
  14.         ;check if route is outstanding subchart route
  15.  
  16. get_hor_stem:
  17.         mov ax,w box_route    ;load box route
  18.         mov dx,ax    ;save it
  19.         call get_box_par    ;get its route box
  20.         cmp ax,dx    ;is it a outstanding route?
  21.         mov al,'?'    ;load outstanding route character
  22.         je ret    ;create rest of route string
  23.  
  24.         ;get box of route
  25.  
  26.         mov di,o number_buffer    ;load offset
  27.         mov ax,': '    ;load separator
  28.         stosw    ;store it at start of buffer
  29.         mov ax,dx    ;get box of route
  30.         mov bx,w[si]    ;load element offset
  31.         call get_route
  32.         mov dx,ax    ;save it
  33.         sub ax,first_box-1    ;calculate box number
  34.         call store_number2    ;convert it to string
  35.         sub di,o number_buffer    ;calculate size of string in buffer
  36.         mov cx,di
  37.  
  38.         ;copy route path to start of descripter store
  39.  
  40.         mov di,o descripter_string    ;load destination offset
  41.         sub di,cx    ;calculate offset to start of string
  42.         mov bx,di    ;save it
  43.         push cx    ;save count
  44. a1:
  45.         std    ;read backwards
  46.         lodsb    ;load character from start of buffer
  47.         cld    ;write forwards
  48.         stosb    ;store character at end of buffer
  49.         loop a1    ;decrement loop count
  50.  
  51.         ;copy part or all of box route descripter string to buffer
  52.  
  53.         mov ax,dx    ;load box of route
  54.         call get_box_descripter    ;get descripter string length and offset
  55.         cmp cx,13    ;is it bigger than 13
  56. if a        mov cx,13    ;load string size if it is
  57.         pull dx    ;restore count of path
  58.         add dx,cx    ;add it to descripter
  59.         mov di,o descripter_string    ;load offset to descripter buffer
  60.         rep
  61.         movsb    ;copy string
  62.         mov ds,ax,cs    ;restore data segment register
  63.         ret    ;exit
  64.  
  65.         ;write trailing stem to screen with indicator string at top of stem
  66.  
  67. connect:
  68.         mov dx,w cursor_pos    ;load cursor coordinates
  69.         mov cx,5    ;calculate length of stem
  70.         sub cx,w stem_start
  71.         jcxz >b1    ;write bottom of stem character if nul
  72.         add w cursor_pos+1,cx    ;add count to cursor column
  73.         call write_stem    ;write stem to screen
  74.  
  75.         ;write bottom of stem character
  76.  
  77. b1:
  78.         mov al,'╨'    ;load character
  79.         call cursor    ;position cursor
  80.         inc dh    ;move to next row
  81.         mov w cursor_pos,dx    ;save cursor position
  82.         jmp write_chr    ;write character and exit
  83.  
  84.         ;create subchart
  85.  
  86. create_subchart:
  87.         mov ax,w next_box    ;load new box
  88.         call make_box    ;clear it
  89.     es    mov w[di+parent],bp    ;make subcharts parent current box
  90.         mov bx,child    ;load element offset
  91.         mov dx,w next_box    ;make current box parent of subchart
  92.         call store_current_box_par
  93.  
  94.         ;exit to chart loop
  95.  
  96.         and b box_made,1    ;indicate box created
  97.         mov b chart_flag,2    ;set chart entry flag
  98.         stc    ;exit to chart loop
  99.         ret
  100.  
  101.         ;check if subchart is copied
  102.  
  103. down:
  104.         mov b chart_flag,4    ;set chart entry flag
  105. down2:
  106.         mov bx,child    ;load child element offset
  107.         call get_current_box_par    ;get boxes child status
  108.         mov dx,ax    ;save subchart
  109.         mov bx,parent    ;load parent offset
  110.         call get_box_par    ;get parent of subchart
  111.         cmp ax,bp    ;is it current box?
  112.         je >a1    ;goto subchart if it is
  113.  
  114.         ;push this level onto stack
  115.  
  116.         sub w sub_stack,4    ;increment stack pointer
  117.         les di,w sub_stack    ;load pointer to subchart stack
  118.         xchg ax,bp    ;load current box
  119.         stosw    ;store it in stack
  120.         xchg ax,bp    ;load return box
  121.         stosw    ;store it in stack
  122.  
  123.         ;move down a level
  124.  
  125. a1:
  126.         mov bp,dx    ;make first box in subchart current box
  127.         stc    ;exit to chart loop
  128.         ret
  129.  
  130.         ;move up to parent box from subchart
  131.  
  132. up_option:
  133.         mov b chart_flag,4    ;set chart entry flag
  134.         mov bx,parent    ;load element offset
  135.         call get_current_box_par    ;get parent of subchart
  136.         les si,w sub_stack    ;load pointer to subchart stack
  137.         cmp si,top_stack    ;is stack empty
  138.         je >a1    ;get parent box if not
  139.     es    cmp w[si+2],ax    ;is subchart copied?
  140.         je >a2    ;copy its parent if it is
  141. a1:
  142.         mov bp,ax    ;make parent box current box
  143.         stc    ;exit to chart loop
  144.         ret
  145.  
  146.         ;set current box as subchart step parent box
  147.  
  148. a2:
  149.     es    mov bp,w[si]    ;load box
  150.         add w sub_stack,4    ;move up a level
  151.         stc    ;exit to start of chart loop
  152.         ret
  153.  
  154.         ;end subchart option
  155.  
  156. end_sub_option:
  157.         cmp w key_option,14*2    ;has route been chosen from parent box?
  158. if e        jmp long >b1    ;store route if it has
  159.         mov b new_chart,0    ;indicate chart changed
  160.         mov ax,w route    ;save route select
  161.         mov w subchart_route,ax
  162.         mov ax,w current_route    ;save current route offset
  163.         mov w terminating_route,ax
  164.         xor dx,dx    ;clear route count
  165.         mov bx,parent    ;get parent of subchart
  166.         call get_current_box_par
  167.         mov si,ax    ;save it
  168.         call get_routes    ;copy its routes
  169.         mov bx,no    ;load route offset
  170.         mov w route,yes    ;store route incase there arnt any
  171.  
  172.         ;count number of routes leading from parent box
  173.  
  174. a1:
  175.         mov w[bx+option_routes],0    ;clear extra route option
  176.         mov ax,w[bx+routes]    ;load box route
  177.         cmp ax,1    ;is there a route?
  178.         jbe >a2    ;decrement loop count if not
  179.  
  180.         ;copy route
  181.  
  182.         mov w route,bx    ;save route
  183.         inc dx    ;increment route count
  184.         mov b[bx+option_routes],1    ;add route option
  185. a2:
  186.         sub bx,2    ;move to next route
  187.         jne a1    ;decrement loop count
  188.  
  189.         ;make current box parent box
  190.  
  191.         mov w box_save,bp    ;make main box current box
  192.         mov link_box,bp    ;make link box current box
  193.         mov bp,si    ;make current box parent box
  194.         mov w key_option,14*2    ;set key option
  195.         mov ax,w route    ;copy first route
  196.         mov w current_route,ax
  197.  
  198.         ;check if there is more than one route
  199.  
  200.         cmp dx,1    ;is there?
  201.         jbe >b1    ;end subchart if not
  202.         call create_link_string    ;create link string for descripter
  203.         call write_message    ;write bottom message string to buffer
  204.         db 'Choose route to terminate subchart',0
  205.         jmp set_mode_2    ;write current route to stem string and
  206.  
  207.         ;terminate sub-chart link
  208.  
  209. b1:
  210.         mov ax,w box_save    ;load subchart terminating box
  211.         mov bx,w subchart_route    ;load its route offset
  212.         mov dx,w route    ;copy route to it
  213.         call store_box_par
  214.         mov bp,w box_save    ;make it current box
  215.         xor ax,ax    ;load zero
  216.  
  217.         ;clear variables
  218.  
  219.         mov w box_save,ax    ;clear flag/main box
  220.         mov w key_option,ax    ;clear key option
  221.         mov w insert_mode,ax    ;clear mode
  222.         cmp w terminating_route,0    ;is current box decision box?
  223.         je >a1    ;exit if not
  224.         mov bx,no    ;load route element offset
  225.         call get_current_box    ;get current box pointer
  226.     es    cmp w[di+bx],0    ;is no route active?
  227.         jne >a1    ;exit if it is
  228.     es    mov w[di+bx],1    ;indicate box is decision box
  229.  
  230.         ;clear bottom line message string and exit
  231.  
  232. a1:
  233.         mov b message,0    ;clear message string
  234.         mov b chart_flag,4    ;set chart entry flag
  235.         stc    ;exit to chart loop
  236.         ret
  237.  
  238.         ;link main box to link string
  239.  
  240. create_link_string:
  241.         cmp w box_to_subchart,0    ;is subchart being chosen?
  242.         jne ret    ;exit if it is
  243.         mov di,o link_string    ;load offset to link string
  244.         mov es,ax,cs    ;copy code segment
  245.         mov al,26    ;load right arrow character
  246.         stosb    ;write it to end/start of link string
  247.  
  248.         ;copy any routes selected to end of link string
  249.  
  250.         mov si,o route_string    ;load offset to routes selected string
  251.         cmp b[si],0    ;is there a route string?
  252.         je >a2    ;store link box if not
  253.         mov ax,w[si+1]    ;copy characters from route string
  254.         xchg al,ah    ;swap them as link string is in reverse
  255.         stosw
  256.         lodsb
  257.         stosb
  258.  
  259.         ;copy link box number
  260.  
  261. a2:
  262.         mov ax,w link_box    ;load link box
  263.         sub ax,first_box-1    ;calculate its number
  264.         call store_number2    ;convert it to string
  265.         stosb    ;end string
  266.         ret    ;exit
  267.  
  268.         ;copy subchart option
  269.         ;get leading neighbour route to current box
  270.  
  271. copy_subchart:
  272.         call get_neighbour_route    ;get route
  273.         mov w route_to_subchart,bx    ;save route
  274.         or ax,ax    ;is there a neighbour box?
  275. if e        dec ax    ;indicate no neighbour box if not
  276.         mov w box_to_subchart,ax    ;save neighbour box
  277.         mov w box_save,bp    ;set flag
  278.         mov w subchart_link,bp    ;save current box
  279.         mov w link_box,bp    ;store it as link box
  280.         call write_message    ;write bottom line message prompt
  281.         db 'Choose a subchart to copy',0
  282.         mov b chart_flag,1    ;set chart entry flag
  283.         stc    ;exit to chart loop
  284.         ret
  285.  
  286.         ;write link box to bottom line
  287.  
  288. view:
  289.         mov ax,w link_box    ;load link box
  290.         cmp w key_option,1*2    ;is key option for link
  291. if be        mov ax,w view_box    ;load view box if it is
  292.         call get_box_descripter    ;get box descripter string pointer
  293.  
  294.         ;write box descripter to screen
  295.  
  296.         cmp cx,80    ;is string bigger than screen width?
  297. if a        mov cx,80    ;load screen width if it is
  298.         call clear_line    ;clear bottom line(s)
  299.         mov dx,80+24*256    ;load cursor coords
  300.         sub dl,cl    ;calculate column
  301.         shr dl,1
  302.         call cursor    ;position cursor on bottom line
  303.  
  304.         ;copy string to screen
  305.  
  306. a1:
  307.         lodsb    ;load character from string
  308.         call write_chr    ;write it to bottom line
  309.         loop a1    ;decrement loop count
  310.         mov ds,ax,cs    ;restore data segment register
  311. e1:
  312.         call key    ;wait for keypress
  313.         or ax,1    ;exit to middle of chart loop
  314.         ret
  315.  
  316.         ;go to box option
  317.  
  318. goto:
  319.         call clear_line    ;clear bottom lines
  320.         call writexy    ;write prompt to bottom line
  321.         db 28,24
  322.         db 'Please enter box number',0
  323.         mov b s,0    ;clear number string buffer
  324.  
  325.         ;get input from user
  326.  
  327.         call get_string    ;get box number
  328.         dw s
  329.         db 5,1
  330.         jnc >a1    ;evaulate string if escape not pressed
  331.         or bp,bp    ;wait for next keypress
  332.         ret    ;exit to mid loop
  333.  
  334.         ;evaluate input
  335.  
  336. a1:
  337.         call get_val    ;get box from user
  338.         jc >b1    ;exit with error if not a number
  339.         or dx,dx    ;is number too big?
  340.         jne >b1    ;exit with error if it is
  341.         add ax,first_box-1    ;calculate box number
  342.         cmp ax,w next_box    ;is it valid box?
  343.         jb >a1    ;check if box exists if it is
  344.  
  345.         ;write 'no such box' error message
  346.  
  347. b1:
  348.         call clear_line    ;clear bottom line
  349.         call writexy    ;write error message
  350.         db 34,24
  351.         db 'No such box',0
  352.         jmp e1    ;wait for keypress and exit
  353.  
  354.         ;check if box is active
  355.  
  356. a1:
  357.         mov bx,dx    ;load previous box offset
  358.         mov dx,ax    ;save box
  359.         call get_box_par    ;get previous box
  360.         cmp ax,-1    ;is box deleted?
  361.         je b1    ;exit with error message if not
  362.  
  363.         ;make new box current box
  364.  
  365.         mov bp,dx    ;load current box
  366. goto_box:
  367.         mov w sub_stack,top_stack    ;clear subchart stack
  368.         mov b chart_flag,1    ;load chart entry flag
  369.         cmp w box_save,0    ;is flowchart dormant?
  370. if e        mov b chart_flag,4    ;store chart entry flag if not
  371.         stc    ;exit to start of chart loop
  372.         ret
  373.  
  374.         ;search for specified string
  375.  
  376. search:
  377.         call clear_line    ;clear bottom lines
  378.         call writexy    ;write prompt to bottom line
  379.         db 27,24
  380.         db 'Please enter search string',0
  381.         call get_string    ;get box number
  382.         dw search_string
  383.         db 128,1
  384.         jnc >a1    ;check for upper case if escape not down
  385.         or bp,bp    ;don't exit to menu
  386.         ret    ;exit
  387.  
  388.         ;make search string upper case
  389.  
  390. a1:
  391.         mov dx,cx    ;save size of string
  392.         mov di,o search_string    ;load pointer to start of string
  393.         mov es,ax,cs
  394. a1:
  395.         mov al,b[di]    ;load char
  396.         cmp al,'a'    ;is it lower case?
  397.         jb >a2    ;store it if not
  398.         cmp al,'z'    ;is it lower case?
  399. if be        and al,05fh    ;make it upper case if it is
  400.  
  401. a2:
  402.         stosb    ;write char back
  403.         loop a1    ;move to next character
  404.         mov al,-1    ;terminate 
  405.  
  406.         ;get pointer to first box
  407.  
  408.         mov ax,bp    ;load id for box 1
  409.         inc ax    ;move to next box
  410.         mov cx,w next_box    ;calculate number of boxes to end chart
  411.         sub cx,ax
  412.         jbe >e2    ;exit if at end of chart
  413.         call get_box    ;get pointer
  414.  
  415.         ;check if box is active
  416.  
  417. b1:
  418.     es    cmp w[di],-1    ;has box been deleted?
  419.         je >b2    ;move to next box if not
  420.         push ax,cx,dx,di,es    ;save pointer to box
  421.     es    mov cx,w[di+descripter_length]    ;load length of string
  422.         sub cx,dx    ;calculate number of compares
  423.         jb >b3    ;move to next box if it is
  424.         inc cx
  425.  
  426.         ;get pointer to box descripter
  427.  
  428.     es    les ax,w[di+descripter]    ;load address to descripter
  429.         mov dx,es
  430.         call get_pointer    ;get pointer to string
  431.         mov si,o search_string    ;load offset to string
  432. a4:
  433.         xor bx,bx    ;clear sub offset
  434.  
  435.         ;load character from search string
  436.  
  437. a1:
  438.     es    mov al,b[di+bx]    ;load character from descripter
  439.         cmp al,'a'    ;is it lower case?
  440.         jb >a2    ;compare with search string if it is
  441.         cmp al,'z'    ;is it lower case?
  442. if be        and al,05fh    ;make it upper case if it is
  443.  
  444.         ;compare characters
  445.  
  446. a2:
  447.         or al,al    ;convert to zero?
  448. if e        mov al,07fh    ;substitute for marker
  449.         cmp al,b[si+bx]    ;do characters match?
  450.         jne >a3    ;move to next start character
  451.         inc bx    ;move to next character in search string
  452.         cmp b[si+bx],0    ;end of search string?
  453.         jne a1    ;compare next character if not
  454.  
  455.         ;make box with found string current box
  456.  
  457.         pull es,di,dx,cx,ax    ;restore registers
  458.         mov bp,ax    ;copy box with found string
  459.         jmp goto_box    ;change current box
  460. a3:
  461.         inc di    ;move to next character in descripter
  462.         loop a4    ;reset sub offset
  463.  
  464.         ;move to next box
  465.  
  466. b3:
  467.         pull es,di,dx,cx,ax    ;restore pointer to box records
  468. b2:
  469.         call add_record    ;move to next box
  470.         inc ax    ;increment box id
  471.         loop b1    ;check if next box is active
  472.  
  473.         ;write 'no such box' error message
  474.  
  475. e2:
  476.         call clear_line    ;clear bottom line
  477.         call writexy    ;write error message
  478.         db 28,24
  479.         db 'Search string not found',0
  480.         jmp e1    ;wait for keypress and exit
  481.  
  482.         ;ammend box description option
  483.  
  484. ammend:
  485.         mov b chart_flag,4    ;set chart loop entry flag
  486.         mov ax,bp    ;load current box
  487.         call get_box_descripter    ;get pointer to its descripter string
  488.         mov di,o s    ;load offset to buffer
  489.         mov es,ax,cs    ;copy code segment
  490.         mov bx,cx    ;save size of string
  491.         rep
  492.         movsb    ;copy string
  493.         xor al,al    ;load zero
  494.         stosb    ;end string
  495.  
  496.         ;edit string
  497.  
  498.         mov ds,ax,cs    ;restore data segment register
  499.         call get_string    ;edit string
  500.         dw s    ;buffer for string
  501.         db 128,0    ;maximum string size
  502.  
  503.         ;calculate size of block to move
  504.  
  505.         mov ax,w start_free_memory    ;copy address to end of data
  506.         mov w shift_count,ax
  507.         mov ax,w start_free_memory+2
  508.         mov w shift_count+2,ax
  509.         push cx    ;save new string length
  510.  
  511.         ;add old string size to pointer
  512.  
  513.         call get_current_box
  514.     es    mov ax,w[di+descripter]    ;load descripter address
  515.     es    mov dx,w[di+descripter+2]
  516.         call get_pointer    ;convert it to pointer
  517.         push di,es    ;save pointer
  518.         add ax,bx    ;add size of initial string
  519.         adc dx,0
  520.         push ax,dx,bx,cx    ;save string address and string sizes
  521.         sub w shift_count,ax    ;calculate size of data to move
  522.         sbb w shift_count+2,dx
  523.  
  524.         ;check whether new string is bigger or smaller
  525.  
  526.         mov si,cx
  527.         sub cx,bx    ;is string bigger?
  528.         jnc >b1    ;move data down if not
  529.  
  530.         ;shift descripter data down
  531.  
  532.         sub bx,si    ;calculate margin
  533.         mov si,ax
  534.         mov di,ax    ;calculate source address
  535.         sub di,bx
  536.         mov ax,dx
  537.         sbb ax,0
  538.  
  539.         ;shift bytes down
  540.  
  541.         call address_segment    ;convert high addresses to segment
  542.         mov es,ax    ;copy segment values
  543.         mov ds,dx
  544.         call shift_down    ;shift data
  545.         mov ds,ax,cs    ;restore data segment
  546.         jmp >c1    ;copy string
  547.  
  548.         ;calculate pointers
  549.  
  550. b1:
  551.         mov si,w start_free_memory    ;load address to top of data
  552.         mov ax,w start_free_memory+2
  553.         mov di,si    ;calculate destination pointer
  554.         mov dx,ax
  555.         add di,cx    ;add margin
  556.         adc dx,0
  557.  
  558.         ;shift bytes up
  559.  
  560.         call address_segment    ;convert high address to segments
  561.         mov es,dx    ;copy segment values
  562.         mov ds,ax
  563.         call shift_up    ;shift data
  564.         mov ds,ax,cs    ;restore data segment
  565.  
  566.         ;copy new string to store
  567.  
  568. c1:
  569.         pull ax,dx    ;restore string sizes
  570.         sub ax,dx    ;calculate margin
  571.         cwd    ;sign extend it
  572.         mov bx,ax    ;save it
  573.         mov si,dx
  574.         pull dx,ax    ;restore old descripter store address
  575.         pull es,di,cx    ;restore destination pointer and count
  576.         push cx,si    ;save high word of margin
  577.         mov si,o s    ;load source offset to new string
  578.         rep
  579.         movsb    ;copy string
  580.         pull si,cx    ;restore margin high word
  581.         mov b new_chart,0    ;indicate chart changed
  582.         or bx,bx    ;is there a change in memory size?
  583.         stc    ;exit to start of chart loop
  584.         je ret    ;exit if not
  585.  
  586.         ;update box descripter addresses
  587.  
  588.         call get_current_box    ;get pointer to current box
  589.     es    mov w[di+descripter_length],cx    ;store new descripter length
  590. update_descripters:
  591.         push ax    ;save address low word
  592.         mov ax,first_box    ;load first box
  593.         call get_box    ;get its pointer
  594.         mov cx,w next_box    ;load next box number
  595.         sub cx,ax    ;calculate number of boxes to check
  596.         pull ax    ;restore address
  597.  
  598.         ;compare address of start of shifted data with box descripter address
  599.  
  600. a1:
  601.     es    cmp dx,w[di+descripter+2]    ;is data above box string address
  602.         ja >a2    ;decrement loop count if it is
  603.         jb >a3    ;update address if not
  604.     es    cmp ax,w[di+descripter]    ;is data above box string address
  605.         ja >a2    ;decrement loop count if it is
  606.  
  607.         ;update box descripter address
  608.  
  609. a3:
  610.     es    add w[di+descripter],bx    ;add margin to address
  611.     es    adc w[di+descripter+2],si
  612. a2:
  613.         call add_record    ;move to next box
  614.         loop a1    ;decrement loop count
  615. b1:
  616.         add w start_free_memory,bx    ;update ram top address
  617.         adc w start_free_memory+2,si
  618.         or ax,1    ;exit to middle of chart loop
  619.         ret    ;exit
  620.  
  621.         ;convert high words to segment format
  622.  
  623. address_segment:
  624.         shl ax,1
  625.         shl dx,1
  626.         shl ax,1
  627.         shl dx,1
  628.         shl ax,1
  629.         shl dx,1
  630.         shl ax,1
  631.         shl dx,1
  632.         shl ax,1
  633.         shl dx,1
  634.         shl ax,1
  635.         shl dx,1
  636.         shl ax,1
  637.         shl dx,1
  638.         shl ax,1
  639.         shl dx,1
  640.         shl ax,1
  641.         shl dx,1
  642.         shl ax,1
  643.         shl dx,1
  644.         shl ax,1
  645.         shl dx,1
  646.         shl ax,1
  647.         shl dx,1
  648.         ret    ;exit
  649.  
  650.         ;create box and adjust pointers to descripter strings area
  651.  
  652. make_box:
  653.         push ax,bx,cx,dx,si    ;save registers
  654.         mov si,w start_free_memory    ;load address to top of data
  655.         mov w shift_count,si    ;save it
  656.         mov bx,w start_free_memory+2
  657.         mov w shift_count+2,bx
  658.         mov ax,w next_box    ;load new box
  659.         call get_box_address    ;get box address in ax:dx
  660.         push ax,dx    ;save it
  661.         sub w shift_count,ax    ;calculate number of bytes to shift
  662.         sbb w shift_count+2,dx
  663.  
  664.         ;calculate pointers for descripter string area shift
  665.  
  666.         mov di,si    ;load offset to end of data
  667.         mov cx,bx    ;load segment
  668.         add di,box_record    ;add box record size
  669.         adc cx,0
  670.  
  671.         ;convert segment words to segment format
  672.  
  673.         mov ax,cx
  674.         mov cl,12
  675.         shl ax,cl
  676.         shl bx,cl
  677.  
  678.         ;shift descripter string area
  679.  
  680.         mov es,ax    ;load segments
  681.         mov ds,bx
  682.         call shift_up    ;shift bytes
  683.         mov ds,ax,cs    ;restore data segment register
  684.  
  685.         ;update all boxes addresses to their descripters
  686.  
  687.         mov ax,w chart    ;load address to start of boxes
  688.         mov dx,w chart+2
  689.         call get_pointer    ;convert it to pointer
  690.         mov cx,w next_box    ;calculate number of boxes in memory
  691.         sub cx,first_box
  692.         pull dx,ax    ;restore address of box
  693.         jcxz >a2    ;clear record if no other boxes
  694. a1:
  695.     es    add w[di+descripter],box_record    ;add record size to address
  696.     es    adc w[di+descripter+2],0
  697.         call add_record    ;move to next box record
  698.         loop a1    ;decrement loop count
  699.  
  700.         ;clear new box
  701.  
  702.         call get_pointer    ;convert it to pointer
  703. a2:
  704.         push di    ;save offset
  705.         xor ax,ax    ;load zero
  706.         mov cx,descripter/2    ;load element count
  707.         rep
  708.         stosw    ;clear record
  709.  
  710.         ;copy address of box descripter
  711.  
  712.         add w start_free_memory,box_record    ;move address to end of data
  713.         adc w start_free_memory+2,0
  714.         mov ax,w start_free_memory    ;copy address to top of memory
  715.         stosw
  716.         mov ax,w start_free_memory+2
  717.         stosw
  718.  
  719.         ;exit
  720.  
  721.         pull di,si,dx,cx,bx,ax    ;restore registers
  722.         ret    ;exit
  723.  
  724.         ;shift text up
  725.         ;entry:
  726.         ;number of bytes to shift in 32 bit store shift_count
  727.         ;ds:si source pointer
  728.         ;es:di destination pointer
  729.  
  730. shift_up:
  731.         dec si,si,di,di    ;move back over last word
  732.         std    ;set direction flag for    moving down
  733. b1:
  734.         call load_count    ;load count of bytes to move
  735.         xor ax,ax    ;exit if finished
  736.         jcxz >c1
  737.  
  738.         ;range check pointers
  739.  
  740.         cmp di,cx    ;is there enough space below?
  741.         ja >a1    ;convert count if there is
  742.         mov dx,cx    ;load maximum size needed
  743.         sub dx,di    ;calculate neccessary margin
  744.         add dx,010h    ;add a paragraph
  745.         and dx,0fff0h    ;mask out loose    bytes
  746.         add di,dx    ;add margin to offset
  747.         shr dx,1    ;convert to segment
  748.         shr dx,1
  749.         shr dx,1
  750.         shr dx,1
  751.         mov ax,es    ;load segment
  752.         sub ax,dx    ;adjust    it
  753.         mov es,ax
  754.  
  755.         ;adjust source pointer if not enough room for transfer
  756.  
  757. a1:
  758.         cmp si,cx    ;is there enough space below?
  759.         ja >a1    ;exit if there is
  760.         mov dx,cx    ;load maximum size needed
  761.         sub dx,si    ;calculate neccessary margin
  762.         add dx,010h    ;add a paragraph
  763.         and dx,0fff0h    ;mask out loose    bytes
  764.         add si,dx    ;add margin to offset
  765.         shr dx,1    ;convert to segment
  766.         shr dx,1
  767.         shr dx,1
  768.         shr dx,1
  769.         mov ax,ds    ;load segment
  770.         sub ax,dx    ;adjust    it
  771.         mov ds,ax
  772.  
  773.         ;copy data
  774.  
  775. a1:
  776.         mov ax,cx    ;load shift count
  777.         shr cx,1    ;half it
  778.         rep
  779.         movsw
  780.         test ax,1    ;is shift count odd?
  781.         je b1    ;load count for next batch if not
  782.         inc si,di    ;increment offsets
  783.         movsb    ;move byte
  784.         jmp b1    ;load count
  785. c1:
  786.         cld    ;restore direction flag
  787.         ret    ;exit
  788.  
  789.         ;shift text down
  790.         ;number of bytes to shift in 32 bit store shift_count
  791.         ;ds:si source pointer
  792.         ;es:di destination pointer
  793.         ;adjust destination pointer if not enough room for transfer
  794.  
  795. shift_down:
  796.         call load_count    ;load count of bytes to move
  797.         xor ax,ax    ;exit if finished
  798.         jcxz ret
  799.         call range_check_pointers    ;range check both pointers
  800.         mov ax,cx    ;load shift count
  801.         shr cx,1    ;half it
  802.         rep
  803.         movsw
  804.         test ax,1    ;is shift count odd?
  805.         je shift_down    ;get count for next batch if not
  806.         movsb    ;move byte
  807.         jmp shift_down    ;move them if yes
  808.  
  809.         ;check if there is enough space above destination index register
  810.  
  811. range_check_sptr:
  812.         mov ax,si    ;calculate amount of space above
  813.         not ax    ;pointer
  814.         cmp ax,cx    ;is there enough space above?
  815.         jae ret    ;exit if there is
  816.         push bx    ;save register
  817.         mov bx,cx    ;load maximum size needed
  818.         sub bx,ax    ;calculate neccessary margin
  819.         add bx,010h    ;add a paragraph
  820.         and bx,0fff0h    ;clear low nybble
  821.         sub si,bx    ;add margin to offset
  822.         shr bx,1    ;convert to segment
  823.         shr bx,1
  824.         shr bx,1
  825.         shr bx,1
  826.         mov ax,ds    ;load segment
  827.         add ax,bx    ;adjust    it
  828.         mov ds,ax
  829.         pull bx    ;restore register
  830.         ret    ;exit
  831.  
  832.         ;range check destination pointer
  833.  
  834. range_check_pointers:
  835.         call range_check_sptr    ;range check source pointer
  836.  
  837.         ;range check destination pointer (es:di)
  838.  
  839. range_check_dptr:
  840.         mov ax,di    ;calculate amount of space above
  841.         not ax    ;pointer
  842.         cmp ax,cx    ;is there enough space above?
  843.         jae ret    ;exit if there is
  844.         push bx    ;save register
  845.         mov bx,cx    ;load maximum size needed
  846.         sub bx,ax    ;calculate neccessary margin
  847.         add bx,010h    ;add a paragraph
  848.         and bx,0fff0h    ;clear low nybble
  849.         sub di,bx    ;add margin to offset
  850.         shr bx,1    ;convert to segment
  851.         shr bx,1
  852.         shr bx,1
  853.         shr bx,1
  854.         mov ax,es    ;load segment
  855.         add ax,bx    ;adjust    it
  856.         mov es,ax
  857.         pull bx    ;restore register
  858.         ret    ;exit
  859.  
  860.         ;load cx with maximum count
  861.  
  862. load_count:
  863.         mov cx,0ffceh    ;load maximum shift count
  864.     cs    cmp w shift_count+2,0    ;is shift count    greater    than a segment?
  865.         ja >a1    ;exit if it is
  866.     cs    cmp w shift_count,0ffeeh    ;is count greater?
  867.         ja >a1    ;exit if not
  868.     cs    mov cx,w shift_count    ;load rest of bytes to shift
  869.  
  870.         ;subtract size of block from count
  871.  
  872. a1:
  873.     cs    sub w shift_count,cx    ;subtract sub count from count
  874.     cs    sbb w shift_count+2,0
  875.         ret    ;exit
  876.  
  877.         ;add box record to pointer ds:si
  878.  
  879. add_record2:
  880.         cmp si,-box_record*4    ;is there enough room to add a record?
  881.         jb >a1    ;add it if there is
  882.         sub si,08000h    ;make enough room in offset
  883.         push ax    ;save register
  884.         mov ax,ds    ;adjust segment
  885.         add ax,0800h
  886.         mov ds,ax
  887.         pull ax    ;restore register
  888. a1:
  889.         add si,box_record    ;move to next record
  890.  
  891.         ;add box record to pointer es:di
  892.  
  893. add_record:
  894.         cmp di,-box_record*4    ;is there enough room to add a record?
  895.         jb >a1    ;add it if there is
  896.         sub di,08000h    ;make enough room in offset
  897.         push ax    ;save register
  898.         mov ax,es    ;adjust segment
  899.         add ax,0800h
  900.         mov es,ax
  901.         pull ax    ;restore register
  902. a1:
  903.         add di,box_record    ;move to next record
  904.         ret    ;exit
  905.  
  906.         ;return box pointer in es:di
  907.  
  908. get_current_box:
  909.         push ax    ;save register
  910.         mov ax,bp    ;load current box
  911.         jmp >a1    ;get its pointer
  912. get_box:
  913.         push ax    ;save register
  914. a1:
  915.         push bx,cx,dx    ;save registers
  916.         call get_box_address    ;get pointer to box
  917.         call get_pointer
  918.         pull dx,cx,bx,ax    ;restore registers
  919.         ret    ;exit
  920.  
  921.         ;calculate box offset
  922.  
  923. get_box_address:
  924.         push bx,cx    ;save registers
  925.         sub ax,first_box    ;calculate box number
  926.         cwd    ;sign extend it
  927.         shl ax,1    ;x 2
  928.         rcl dx,1
  929.         mov bx,ax    ;save it
  930.         mov cx,dx
  931.         shl ax,1    ;x 4
  932.         rcl dx,1
  933.         shl ax,1    ;x 8
  934.         rcl dx,1
  935.         shl ax,1    ;x 16
  936.         rcl dx,1
  937.         add ax,bx    ;X18
  938.         adc dx,cx
  939.         add ax,w chart    ;add it to start of box records address
  940.         adc dx,w chart+2
  941.         pull cx,bx    ;restore registers
  942.         ret    ;exit
  943.  
  944.         ;get pointer to top of ram
  945.  
  946. get_pointer2:
  947.         mov ax,w start_free_memory    ;load address to top of data
  948.         mov dx,w start_free_memory+2
  949.  
  950.         ;convert high word to segment format
  951.  
  952. get_pointer:
  953.         push ax,dx    ;save registers
  954.         shl dx,1    ;move segment nybble to top end
  955.         shl dx,1
  956.         shl dx,1
  957.         shl dx,1
  958.         shl dx,1
  959.         shl dx,1
  960.         shl dx,1
  961.         shl dx,1
  962.         shl dx,1
  963.         shl dx,1
  964.         shl dx,1
  965.         shl dx,1
  966.  
  967.         ;return pointer in es:di
  968.  
  969.         mov es,dx    ;load segment
  970.         mov di,ax    ;load offset
  971.         cmp di,-(box_record*4)    ;is there enough room in offset?
  972.         jb >a1    ;exit if there is
  973.         sub di,08000h    ;subtract a page
  974.         mov ax,es    ;adjust segment
  975.         add ax,0800h
  976.         mov es,ax
  977. a1:
  978.         pull dx,ax    ;restore registers
  979.         ret    ;exit
  980.  
  981.         ;return box parameter
  982.  
  983. get_current_box_par:
  984.         xor ax,ax    ;load zero
  985.         or bp,bp    ;is there a current box?
  986.         je ret    ;exit if not
  987.         mov ax,bp    ;load current box
  988. get_box_par:
  989.         or ax,ax    ;is box valid?
  990.         je ret    ;exit if not
  991.         push di,es    ;save pointer
  992.         call get_box    ;get pointer to box
  993.     es    mov ax,w[di+bx]    ;get parameter from box record
  994.         pull es,di    ;restore pointer
  995.         ret    ;exit
  996.  
  997.         ;store box parameter
  998.  
  999. store_current_box_par:
  1000.         xchg ax,bp    ;load current box
  1001.         call store_box_par    ;store box parameter
  1002.         xchg ax,bp    ;restore register
  1003.         ret    ;exit
  1004.  
  1005.         ;store box parameter
  1006.  
  1007. store_box_par:
  1008.         push di,es    ;save pointer
  1009.         call get_box    ;get pointer to box
  1010.     es    mov w[di+bx],dx    ;store parameter to box record
  1011.         pull es,di    ;restore pointer
  1012.         ret    ;exit
  1013.  
  1014.         ;get pointer to box descripter
  1015.  
  1016. get_box_descripter:
  1017.         push dx,di,es    ;save pointer
  1018.         call get_box    ;get box pointer
  1019.     es    mov cx,w[di+descripter_length]    ;load string size
  1020.     es    les si,w[di+descripter]    ;load pointer to descripter string
  1021.  
  1022.         ;convert segment word to segment format
  1023.  
  1024.         mov dx,es    ;load segment word
  1025.         shl dx,1
  1026.         shl dx,1
  1027.         shl dx,1
  1028.         shl dx,1
  1029.         shl dx,1
  1030.         shl dx,1
  1031.         shl dx,1
  1032.         shl dx,1
  1033.         shl dx,1
  1034.         shl dx,1
  1035.         shl dx,1
  1036.         shl dx,1
  1037.         cmp si,0ff80h    ;is there enough room in string for copy
  1038.         jb >a1    ;exit if there is
  1039.         sub si,0100h    ;subtract a page from pointer
  1040.         add dx,010h
  1041. a1:
  1042.         mov ds,dx    ;store segment of pointer
  1043.         pull es,di,dx    ;restore pointer
  1044.         ret    ;exit
  1045.  
  1046.         ;read value from configuration file
  1047.  
  1048. get_val:
  1049.         jcxz >c1    ;exit if error
  1050. b1:
  1051.         lodsb    ;load character from file
  1052.  
  1053.         ;check if next character is numeric
  1054.  
  1055.         dec si    ;move offset over first character
  1056.         mov bx,si    ;save offset to line
  1057. a1:
  1058.         jcxz >a2    ;convert ascii digits to number
  1059.         lodsb    ;load character from line
  1060.         dec cx
  1061.         cmp al,'0'    ;is character below ascii 0?
  1062.         jb >c1    ;exit if it is
  1063.         cmp al,'9'    ;is character above ascii 9?
  1064.         jbe a1    ;get next character if not
  1065.  
  1066.         ;exit indicating error
  1067.  
  1068. c1:
  1069.         stc    ;indicate error
  1070.         ret    ;exit
  1071.  
  1072.         ;check if last character is carriage return
  1073.  
  1074. a2:
  1075.         push cx,si    ;save file count and offset
  1076.         mov cx,si    ;load offset to end of number
  1077.         sub cx,bx    ;calculate length of string
  1078.         mov w temp1,1    ;store multiplier
  1079.         mov w temp1+2,0
  1080.         mov w temp3,0    ;clear return value
  1081.         mov w temp3+2,0
  1082.         dec si    ;move offset over last digit
  1083.         std    ;set direction flag
  1084.  
  1085.         ;get digit
  1086.  
  1087. a1:
  1088.         lodsb    ;load digit from configuration file
  1089.         sub al,'0'    ;take away base
  1090.         xor ah,ah    ;clear high register
  1091.         xor bx,bx    ;load product
  1092.         xor dx,dx
  1093.         push cx    ;save count
  1094.         mov cx,16    ;load bit count
  1095.  
  1096.         ;mulitply digit by ten base
  1097.  
  1098. a2:
  1099.         shl bx,1    ;multiply product by 2
  1100.         rcl dx,1
  1101.         shl ax,1    ;shift multiplier left one
  1102.         jnc >a3    ;decrement loop count if no carry
  1103.         add bx,w temp1    ;add multiplicand to product
  1104.         adc dx,w temp1+2
  1105. a3:
  1106.         loop a2    ;decrement loop count
  1107.         add w temp3,bx    ;add product to return value
  1108.         adc w temp3+2,dx
  1109.  
  1110.         ;mulitiply multiplicand by ten
  1111.  
  1112.         mov ax,w temp1    ;load it
  1113.         mov dx,w temp1+2
  1114.         shl ax,1    ;multiply it by 4
  1115.         rcl dx,1
  1116.         shl ax,1
  1117.         rcl dx,1
  1118.         add ax,w temp1    ;add it by one
  1119.         adc dx,w temp1+2
  1120.         shl ax,1    ;multiply it by 2
  1121.         rcl dx,1
  1122.         mov w temp1,ax    ;store it
  1123.         mov w temp1+2,dx
  1124.         pull cx    ;restore outer loop count
  1125.         loop a1    ;fetch next character
  1126.         cld    ;restore direction flag
  1127.  
  1128.         ;exit with value read in ax:dx
  1129.  
  1130.         mov ax,w temp3    ;load value read
  1131.         mov dx,w temp3+2
  1132.         pull si,cx    ;restore offset and file count
  1133.         clc    ;indicate ok
  1134.         ret    ;exit
  1135.  
  1136.         ;clear screen
  1137.  
  1138. cls:
  1139.     cs    cmp b direct_video,0    ;is screen output direct?
  1140.         jne >a1    ;clear screen direct if it is
  1141.         mov ax,0600h    ;load function parameters
  1142.         mov bh,7    ;load attribute
  1143.         xor cx,cx    ;load top left corner coordinates
  1144.         mov dx,0184fh    ;load bottom right corner coordinates
  1145.         call int10    ;clear the screen
  1146.         ret    ;exit
  1147.  
  1148.         ;clear screen
  1149.  
  1150. a1:
  1151.         xor dx,dx    ;move cursor to top left of screen
  1152.         call cursor    ;position cursor
  1153.         mov ax,0720h    ;load space and attribute
  1154.         mov cx,80*25
  1155.     cs    les di,w video_pointer    ;load pointer to start of map
  1156.         rep
  1157.         stosw
  1158.         mov es,ax,cs    ;copy segment to workspace
  1159.         ret    ;exit
  1160.  
  1161.         ;get keypress
  1162.  
  1163. key:
  1164.         mov ah,01h    ;load keyboard function    parameter
  1165.         int 016h    ;scan keyboard
  1166.         jne >a1    ;exit if key down
  1167.     cs    cmp b middle_5,0    ;is middle 5 on numeric keypad down?
  1168.         je key    ;scan keyboard if not
  1169.  
  1170.         ;only exit if chart is dormant
  1171.  
  1172.         cmp w box_save,0    ;is flowchart dormant?
  1173.         je >b1    ;exit if it is
  1174.     cs    mov b middle_5,0    ;clear flag
  1175.         jmp key    ;wait for next keypress
  1176. b1:
  1177.         stc    ;indicate key down
  1178.         ret    ;exit
  1179.  
  1180.         ;get keypress
  1181.  
  1182. a1:
  1183.         xor ah,ah    ;fetch the key
  1184.         int 016h
  1185.         cmp ax,011b    ;exit with zero set if key is escape
  1186.         clc    ;indicate middle 5 not down
  1187.         ret    ;exit
  1188.  
  1189.         ;end
  1190.